#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <jsoncpp/json/json.h>
#include "Util.hpp"

class Utility;

// #define SELF

namespace ns_Protocol
{
#define SEP " "
#define SEP_LEN strlen(SEP)
#define HEADERS_SEP "\n\t"
#define HEADERS_SEP_LEN strlen(HEADERS_SEP)
    //"1 + 2" --> "7"\n\t"1 + 2"\n\t
    // 返回值：添加报头后的串
    static std::string addHeaders(std::string &str)
    {
        // std::cout << "addHeaders before\n" << str << std::endl;

        std::string s = std::to_string(str.size());
        s += HEADERS_SEP;
        s += str;
        s += HEADERS_SEP;

        // std::cout << "addHeaders after\n" << s << std::endl;
        return s;
    }
    //"7"\n\t"1 + 2"\n\t  --> "1 + 2"
    // n ：有效报文的长度
    // 返回值：去掉报头后的子串
    static std::string removeHeaders(const std::string &str, int len)
    {
        // std::cout << "removeHeaders before\n" << str << std::endl;

        auto pos = str.rfind(HEADERS_SEP);
        std::string s = str.substr(pos - len, len);

        // std::cout << "removeHeaders after\n" << s << std::endl;
        return s;
    }

    //"7"\n\t"1 + 2"\n\t"7"\n\t"3 + 6"\n\t"7"\n\t"5 + 7"\n\t -->"7"\n\t"1 + 2"\n\t
    static int getPackage(std::string &inbuf, std::string *str)
    {
        // std::cout << "getPackage before\ninbuf\n" << inbuf << std::endl;
        // std::cout << "str\n" << str->c_str() << std::endl;

        auto pos = inbuf.find(HEADERS_SEP);
        if (pos == std::string::npos)
            return 0;
        std::string pack_len_str = inbuf.substr(0, pos); // 长度字符串
        int pack_len = Util::toInt(pack_len_str); // 报文的长度
        int len = pack_len + pack_len_str.size() + 2 * HEADERS_SEP_LEN;
        if (inbuf.size() < len)
            return 0;
        *str = inbuf.substr(0, len);
        inbuf.erase(0, len); // 只有获取到了完整的报文，inbuf中的数据才能删除

        // std::cout << "getPackage after\ninbuf\n" << inbuf << std::endl;
        // std::cout << "str\n" << str->c_str() << std::endl;
        return pack_len;
    }

    // 请求
    class Request
    {
    public:
        Request(int x = -1, int y = -1, char op = 0) : 
        _x(x),
        _y(y),
        _op(op)
        {
        }
        // 做一个规定：
        // 输入: const &
        // 输出: *
        // 输入输出: &

        // struct --> string
        // 1+2 --> "1 + 2"
        bool Serialize(std::string *s)
        {
            // std::cout << "Serialize before\n" << *s << std::endl;
#ifdef SELF
            std::string x_str = std::to_string(_x);
            std::string y_str = std::to_string(_y);
            char op = _op;
            *s = x_str;
            *s += SEP;
            *s += op;
            *s += SEP;
            *s += y_str;

#else
            Json::Value root; // 定义一个万能的变量，可以存储任意类型
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            // Json::FastWriter writer; // json序列是一行
            Json::StyledWriter writer; //json序列有特定的格式
            *s = writer.write(root); // write将Value对象Json化，并返回一个串
#endif
            // std::cout << "Serialize after\n" << *s << std::endl;

            return true;
        }

        //"1 + 2" --> 1 + 2
        bool Deserialize(std::string &str)
        {
            // std::cout << "Deserialize before\n";
            Print();
#ifdef SELF
            //"1 + 2" --> [0]->"1" [1]->"+" [2]->"2"
            std::vector<std::string> v;
            size_t pos = 0;
            size_t start = 0;
            //[start,pos)不管截到的，还是获取的都是前闭后开的区间

            std::cout << "Deserialize \n";
            while (pos != std::string::npos)
            {
                //"1 + 2"
                pos = str.find(SEP, start);
                // substr的第二个参数是长度
                //  std:: string sub = str.substr(start,pos);  error
                std::string sub = str.substr(start, pos - start);
                std::cout << "sub " << sub.c_str() << std::endl;
                // 56 * 56
                v.push_back(sub);
                start = pos + SEP_LEN;
            }
            if (v.size() != 3)
            {
                std::cout << "size != 3" << std::endl;
                return false;
            }
            // if(v[0].size() != 1)
            if (v[1].size() != 1)
            {
                std::cout << "v[0].size() != 1" << std::endl;
                return false;
            }

            _x = Utility::toInt(v[0]);
            _y = Utility::toInt(v[2]);
            // _op = v[1][1];
            _op = v[1][0]; // 你写个[1][1]是什么意思啊？！！
#else
            Json::Value root;
            Json::Reader read;
            read.parse(str, root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
#endif
            // std::cout << "Deserialize after\n";
            Print();

            return true;
        }
        void Print()
        {
            std::cout << "_x = " << _x << std::endl;
            std::cout << "_y = " << _y << std::endl;
            printf("_op = %c\n", _op);
        }
        ~Request() {}

    public:
        int _x;
        int _y;
        int _op;
    };
    // 响应
    class Response
    {
    public:
        Response(int result = 0, int code = 0) : 
        _code(code),
        _result(result)
        {
        }
        // 1 2 --> "1 2"
        bool Serialize(std::string *s)
        {
            // std::cout << "Serialize before\n" << *s << std::endl;
#ifdef SELF
            std::string result_str = std::to_string(_result);
            std::string code_str = std::to_string(_code);
            *s = result_str;
            *s += SEP;
            *s += code_str;

#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            // Json::FastWriter writer;
            Json::StyledWriter writer;
            *s = writer.write(root);
#endif
            // std::cout << "Serialize after\n" << *s << std::endl;

            return true;
        }

        //"1  2" --> 1  2
        bool Deserialize(std::string &str)
        {
            // std::cout << "Deserialize before\n";
            Print();
#ifdef SELF
            //"1  0" --> [0]->"1"  [2]->"0"
            std::vector<std::string> v;
            size_t pos = 0;
            size_t start = 0;
            //[start,pos)不管截到的，还是获取的都是前闭后开的区间
            while (pos != std::string::npos)
            {
                //"1  2"
                pos = str.find(SEP, start);
                std::string sub = str.substr(start, pos);
                v.push_back(sub);
                start = pos + SEP_LEN;
            }
            if (v.size() != 2)
            {
                std::cout << "size != 2" << std::endl;
                return false;
            }
            _result = Utility::toInt(v[0]);
            _code = Utility::toInt(v[1]);
#else
            Json::Value root;
            Json::Reader read;
            read.parse(str, root);
            _result = root["result"].asInt();
            _code = root["code"].asInt();
#endif
            // std::cout << "Deserialize after\n";
            Print();
            return true;
        }
        void Print()
        {
            std::cout << "_result = " << _result << std::endl;
            std::cout << "_code = " << _code << std::endl;
        }
        ~Response() {}

    public:
        int _result;
        int _code;
    };
}